package com.pengcheng.swpush.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Component
public class Common {
    public Common() {
    }

    public String byte2hex(byte[] bs)
    {
        String res="";
        for(int i=0;i<bs.length;i++)
        {
            String hex = Integer.toHexString((bs[i] & 0xFF)).toUpperCase();
            hex=hex.length()>1?hex:("0"+hex);
            res+=hex;
        }
        return res;
    }

    public byte[] hex2byte(String str)
    {
        byte[] bs=new byte[str.length()/2];
        for(int i=0;i<str.length()/2;i++)
        {
            String s=str.substring(i*2,i*2+2);
            byte b= (byte)Integer.parseInt(s,16);
            bs[i]=b;
        }
        return bs;
    }

    public float hexstringtofloat(String str)
    {
        long floatbits=Long.parseLong(str,16);
        return Float.intBitsToFloat((int)floatbits);
    }
    public double hexstringtodouble(String str)
    {
        long floatbits=Long.parseLong(str,16);
        return Double.longBitsToDouble(floatbits);
    }
    public String floattohex(float f)
    {
        int floatbits=Float.floatToIntBits(f);
        return Integer.toHexString(floatbits);
    }
    public String doubletohex(double d)
    {
        long doublebits=Double.doubleToLongBits(d);
        return Long.toHexString(doublebits);
    }

    public String tojson(Object obj)
    {
        ObjectMapper mapper=new ObjectMapper();
        String res="";
        try {
            res=mapper.writeValueAsString(obj);
        }
        catch (Exception ex)
        {
            log.info(ex.toString());
        }
        return res;
    }
    public int calculate(byte[] data) {
        int crc = 0xFFFF;
        int POLY = 0xA001;
        for (byte b : data) {
            crc ^= (int) b & 0xFF;
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x0001) != 0) {
                    crc = (crc >> 1) ^ POLY;
                } else {
                    crc = crc >> 1;
                }
            }
        }
        return crc;
    }
    public String calculate_old(byte[] data) {
        int i;
        int crc = 0;
        for(int j=0;j<data.length;j++) {
            crc ^= data[j]&0xFF;
            for ( i = 0; i < 8; i++ )
            {
                if ( (crc & 0x80) == 0)
                    crc <<= 1;
                else
                    crc = ((crc << 1) ^ 0xE5);
            }
        }
        String hex = Integer.toHexString((crc & 0xFF)).toUpperCase();
        return hex;
    }
    public String hexToASCII(String uuid) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < uuid.length(); i += 2) {
            String hex = uuid.substring(i, i + 2);
            int decimal = Integer.parseInt(hex, 16);
            char asciiChar = (char) decimal;
            sb.append(asciiChar);
        }
        String result = sb.toString();
        return result;
    }
    public Map<String,Object> decode(String msg)
    {
        if(msg.length()<6)
        {
            return null;
        }
        int flowrate=0;//瞬时流量
        float speed=0f;//流速
        double flow=0d;//累计流量
        double p_flow=0d;//正累计流量
        double n_flow=0d;//负累计流量
        int pressure=0;//压力
        int caliber=0;//口径
        double flevel=0d;//液位
        double temperature=0d;//温度
        //获取设备类型
        String type=msg.substring(6,10).toLowerCase();
        if(type.equals("a001")&&msg.length()==39*2)
        {
            flowrate=Integer.parseInt(msg.substring(10,18),16);
            flow=(double)Integer.parseInt(msg.substring(18,26),16)+((double)Integer.parseInt(msg.substring(26,30),16)/1000);
            p_flow=(double)Integer.parseInt(msg.substring(30,38),16)+((double)Integer.parseInt(msg.substring(38,42),16)/1000);
            n_flow=(double)Integer.parseInt(msg.substring(42,50),16)+((double)Integer.parseInt(msg.substring(50,54),16)/1000);
            pressure=Integer.parseInt(msg.substring(54,58),16);
            caliber=Integer.parseInt(msg.substring(58,62),16);
            double banjing=((double)caliber/(double) 2000);
            speed=(float)((double)flowrate/((double)3.1415926*banjing*banjing*(double)3600));
        }
        else if(type.equals("a002")&&msg.length()==41*2)
        {
            flowrate=(int)(hexstringtofloat(msg.substring(10,18))*1000);
            speed=hexstringtofloat(msg.substring(18,26))*1000;
            p_flow=Integer.parseInt(msg.substring(26,34),16)*100000000+Integer.parseInt(msg.substring(34,42),16);
            n_flow=Integer.parseInt(msg.substring(42,50),16)*100000000+Integer.parseInt(msg.substring(50,58),16);
            flevel=hexstringtofloat(msg.substring(58,66));
            flow=p_flow-n_flow;
        }
        else if(type.equals("a003")&&msg.length()==37*2)
        {
            flowrate=(int)(hexstringtodouble(msg.substring(10,26))*1000);
            flow=hexstringtodouble(msg.substring(26,42));
            flevel=hexstringtofloat(msg.substring(42,50));
            temperature=hexstringtofloat(msg.substring(50,58));
        }
        else if(type.equals("a008")&&msg.length()==41*2)
        {
            flowrate=(int)(hexstringtofloat(msg.substring(10,18))*1000);
            speed=hexstringtofloat(msg.substring(18,26));
            p_flow=Float.parseFloat(Integer.parseInt(msg.substring(26,34),16)+"."+Integer.parseInt(msg.substring(34,42),16));
            n_flow=Float.parseFloat(Integer.parseInt(msg.substring(42,50),16)+"."+Integer.parseInt(msg.substring(50,58),16));
            flow=p_flow-n_flow;
        }
        else {
            return null;
        }
        Map<String,Object> map=new HashMap<>();
        map.put("flowrate",flowrate);
        map.put("speed",speed);
        map.put("flow",flow);
        map.put("p_flow",p_flow);
        map.put("n_flow",n_flow);
        map.put("pressure",pressure);
        map.put("caliber",caliber);
        map.put("flevel",flevel);
        map.put("temperature",temperature);
        int start_index_date=msg.length()-(2*8);
        int year=Integer.parseInt(msg.substring(start_index_date,start_index_date+2),16);
        int month=Integer.parseInt(msg.substring(start_index_date+2,start_index_date+4),16);
        int day=Integer.parseInt(msg.substring(start_index_date+4,start_index_date+6),16);
        int hour=Integer.parseInt(msg.substring(start_index_date+6,start_index_date+8),16);
        int minute=Integer.parseInt(msg.substring(start_index_date+8,start_index_date+10),16);
        int second=Integer.parseInt(msg.substring(start_index_date+10,start_index_date+12),16);
        String str_month=month>=10?(month+""):("0"+month);
        String str_day=day>=10?(day+""):("0"+day);
        String str_hour=hour>=10?(hour+""):("0"+hour);
        String str_minute=minute>=10?(minute+""):("0"+minute);
        String str_second=second>=10?(second+""):("0"+second);
        map.put("dyear",(2000+year)+"");
        map.put("dmonth",str_month);
        map.put("dday",str_day);
        map.put("ddate",(2000+year)+"-"+str_month+"-"+str_day+" "+str_hour+":"+str_minute+":"+str_second);
        return map;
    }

    public Map<String,Object> decode_old(String msg)
    {
        if(msg.length()!=62)
        {
            return null;
        }
        try {
            int flowrate=0;//瞬时流量
            float speed=0f;//流速
            double flow=0d;//累计流量
            double p_flow=0d;//正累计流量
            double n_flow=0d;//负累计流量
            int pressure=0;//压力
            int caliber=0;//口径
            double flevel=0d;//液位
            double temperature=0d;//温度
            //获取设备类型
            String sn=msg.substring(8,14).toLowerCase();
            String index=msg.substring(16,18)+msg.substring(14,16);
            index=Integer.parseInt(index,16)+"";
            while (index.length()<4)
            {
                index="0"+index;
            }
            sn=sn+index;
            //获取瞬时流量
            String str_flowrate1=msg.substring(20,22);
            String str_flowrate2=msg.substring(22,24);
            String str_flowrate3=msg.substring(24,26);
            String str_flowrate4=msg.substring(26,28);
            String str_flowrate5=msg.substring(28,30);
            String str_flowrate="";
            if(!str_flowrate5.startsWith("0"))
            {
                str_flowrate="-";
            }
            str_flowrate+=(str_flowrate5.substring(1,2)+str_flowrate4+str_flowrate3+str_flowrate2+str_flowrate1);
            flowrate=Integer.parseInt(str_flowrate);
            //获取瞬时流量
            String str_flow1=msg.substring(30,32);
            String str_flow2=msg.substring(32,34);
            String str_flow3=msg.substring(34,36);
            String str_flow4=msg.substring(36,38);
            String str_flow5=msg.substring(38,40);
            String str_flow="";
            String b_flow5=Integer.toBinaryString(Integer.parseInt(str_flow5));
            while(b_flow5.length()<4)
            {
                b_flow5="0"+b_flow5;
            }
            if(!b_flow5.startsWith("0"))
            {
                str_flow="-";
            }
            b_flow5="0"+b_flow5.substring(1,4);
            str_flow5=Integer.toHexString(Integer.parseInt(b_flow5,2));
            str_flow+=(str_flow5+str_flow4+str_flow3+str_flow2+str_flow1);
            flow=Float.parseFloat(str_flow);
            //获取年，月
            String str_year=msg.substring(44,46);
            String str_month=msg.substring(46,48);
            String str_second=msg.substring(48,50);
            String str_minute=msg.substring(50,52);
            String str_hour=msg.substring(52,54);
            String str_day=msg.substring(54,56);
            int year=get_year(new Date());
            int month=get_month(new Date());
            if(!str_year.equals("00"))
            {
                year=2000+Integer.parseInt(str_year);
            }
            if(!str_year.equals("00"))
            {
                month=Integer.parseInt(str_month);
            }
            int day=Integer.parseInt(str_day);
            if(day<1||day>31)
            {
                return null;
            }
            int hour=Integer.parseInt(str_hour);
            int minute=Integer.parseInt(str_minute);
            int second=Integer.parseInt(str_second);
            String ddate=year+"-"+(month<10?("0"+month):(""+month))+"-"+(day<10?("0"+day):(""+day))+" "+(hour<10?("0"+hour):(""+hour))+":"+(minute<10?("0"+minute):(""+minute))+":"+(second<10?("0"+second):(""+second));
            Map<String,Object> map=new HashMap<>();
            map.put("sn",sn);
            map.put("flowrate",flowrate);
            map.put("speed",speed);
            map.put("flow",flow);
            map.put("p_flow",p_flow);
            map.put("n_flow",n_flow);
            map.put("pressure",pressure);
            map.put("caliber",caliber);
            map.put("flevel",flevel);
            map.put("temperature",temperature);
            map.put("ddate",ddate);
            map.put("dyear",year+"");
            map.put("dmonth",month+"");
            map.put("dday",day+"");
            map.put("dsecond",second+"");
            map.put("dminute",minute+"");
            map.put("dhour",hour+"");
            return map;
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    public byte[] get_response(String msg)
    {
        byte[] res=new byte[11];
        byte[] old=this.hex2byte("014306"+msg.substring(msg.length()-16,msg.length()-4));
        int crc=this.calculate(old);
        for(int i=0;i<9;i++)
        {
            res[i]=old[i];
        }
        byte crcHigh = (byte) ((crc >> 8) & 0xFF);
        byte crcLow = (byte) (crc & 0xFF);
        res[9]=crcLow;
        res[10]=crcHigh;
        return res;
    }
    public String get_response_old(String msg)
    {
        String str_year=msg.substring(44,46);
        String str_month=msg.substring(46,48);
        String str_second=msg.substring(48,50);
        String str_minute=msg.substring(50,52);
        String str_hour=msg.substring(52,54);
        String str_day=msg.substring(54,56);
        String str_state=msg.substring(56,58);
        String res="6808AA00"+str_year+str_month+str_second+str_minute+str_hour+str_day+str_state;
        String crc=calculate_old(hex2byte("00"+str_year+str_month+str_second+str_minute+str_hour+str_day+str_state));
        res+=crc;
        res+="55";
        return res;
    }
    public String get_time_msg(Date d)
    {
        byte[] res=new byte[13];
        long time=d.getTime()/1000;
        String msg="051000C7000204"+Long.toHexString(time);
        byte[] old=this.hex2byte(msg);
        for(int i=0;i<11;i++)
        {
            res[i]=old[i];
        }
        int crc=this.calculate(old);
        byte crcHigh = (byte) ((crc >> 8) & 0xFF);
        byte crcLow = (byte) (crc & 0xFF);
        res[11]=crcLow;
        res[12]=crcHigh;
        return byte2hex(res);
    }
    public String set_interval_msg(int interval)
    {
        String msg="05101201000204";
        String str_intervl=Integer.toHexString(interval);
        while(str_intervl.length()<8)
        {
            str_intervl="0"+str_intervl;
        }
        msg=msg+str_intervl;
        byte[] old=this.hex2byte(msg);
        int crc=this.calculate(old);
        byte crcHigh = (byte) ((crc >> 8) & 0xFF);
        byte crcLow = (byte) (crc & 0xFF);
        String hex_low = Integer.toHexString((crcLow & 0xFF)).toUpperCase();
        hex_low=hex_low.length()>1?hex_low:("0"+hex_low);
        String hex_high = Integer.toHexString((crcHigh & 0xFF)).toUpperCase();
        hex_high=hex_high.length()>1?hex_high:("0"+hex_high);
        msg=msg+hex_low+hex_high;
        return msg;
    }
    public String set_hbeat_msg(String hbeat)
    {
        String msg="051006D2000306";
        msg+=hbeat;
        msg+="00";
        byte[] old=this.hex2byte(msg);
        int crc=this.calculate(old);
        byte crcHigh = (byte) ((crc >> 8) & 0xFF);
        byte crcLow = (byte) (crc & 0xFF);
        String hex_low = Integer.toHexString((crcLow & 0xFF)).toUpperCase();
        hex_low=hex_low.length()>1?hex_low:("0"+hex_low);
        String hex_high = Integer.toHexString((crcHigh & 0xFF)).toUpperCase();
        hex_high=hex_high.length()>1?hex_high:("0"+hex_high);
        msg=msg+hex_low+hex_high;
        return msg;
    }
    public String close_dsend_msg()
    {
//        NAT@AT+SOCKEN1B=OFF
        String msg="4E41544041542B534F434B454E31423D4F4646";
        return msg;
    }
    public String open_dsend_msg()
    {
        String msg="4E41544041542B534F434B454E31423D4F4E";
        return msg;
    }
    public String set_dsend_msg()
    {
        String msg="4E41544041542B534F434B31423D544350432C3232312E3138322E3137332E32362C39303030";
//        String msg="4E41544041542B534F434B31423D544350432C746573742E68756179756E696F742E636F6D2C3630303032";//华云测试服务器
        return msg;
    }
    public String format_date(Date date)
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }
    public String format_exception(Exception ex)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("发生异常: ").append(ex.toString()).append("\n");
        sb.append("异常消息: ").append(ex.getMessage()).append("\n");
        sb.append("堆栈追踪: ").append("\n");
        for (StackTraceElement element : ex.getStackTrace()) {
            sb.append("\t").append(element.toString()).append("\n");
        }
        return sb.toString();
    }
    public Date parse_date(String date)
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(date);
        }
        catch (Exception ex)
        {
            return null;
        }
    }
    public Date make_date(int year,int month,int day)
    {
        String str=year+"-"+(month<10?("0"+month):(""+month))+"-"+(day<10?("0"+day):(""+day))+" 00:00:00";
        return parse_date(str);
    }

    public int get_year(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }
    public int get_month(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH)+1;
    }
    public int get_day(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    public String add_day(int day)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, day);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nextDay = dateFormat.format(calendar.getTime());
        return nextDay;
    }
    public String add_day(Date date,int day)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, day);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nextDay = dateFormat.format(calendar.getTime());
        return nextDay;
    }
    public Date add_month(Date date,int month)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return calendar.getTime();
    }


    public boolean is_empty(String str)
    {
        if(str==null||str.equals(""))
        {
            return true;
        }
        return false;
    }
    public boolean is_number(String str)
    {
        try
        {
            Double.parseDouble(str);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    public boolean is_int(String str)
    {
        try
        {
            Integer.parseInt(str);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public String join(String[] ss)
    {
        String res="";
        for(int i=0;i<ss.length;i++)
        {
            if(i>0)
            {
                res+=",";
            }
            res+=ss[i];
        }
        return res;
    }

    public String join_list(List<String> ss)
    {
        String res="";
        for(int i=0;i<ss.size();i++)
        {
            if(i>0)
            {
                res+=",";
            }
            res+=ss.get(i);
        }
        return res;
    }
    public String join_String(String[] ss)
    {
        String res="";
        for(int i=0;i<ss.length;i++)
        {
            if(i>0)
            {
                res+=",";
            }
            res+=("'"+ss[i]+"'");
        }
        return res;
    }
    public int find_in_array(String s,String[] ss)
    {
        int index=-1;
        for(int i=0;i<ss.length;i++)
        {
            if(ss[i].equals(s))
            {
                return i;
            }
        }
        return index;
    }
    public String convertToUnicode(String input) {
        StringBuilder unicode = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            unicode.append("\\u").append(Integer.toHexString((int) c));
        }
        return unicode.toString();
    }
}
